package com.lintf.starter.central.auth;

import com.lintf.starter.central.auth.cache.CacheStrategy;
import com.lintf.starter.central.auth.cache.MemoryCacheStrategy;
import com.lintf.starter.central.auth.cache.NoOpCacheStrategy;
import com.lintf.starter.central.auth.cache.RedisCacheStrategy;
import com.lintf.starter.central.auth.redis.DefaultRedisOperator;
import com.lintf.starter.central.auth.redis.RedisOperationsAdapter;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.connection.RedisConnectionFactory;

@Slf4j
@Configuration
@EnableConfigurationProperties(CentralAuthProperties.class)
public class CentralAuthAutoConfiguration {

    private final CentralAuthProperties properties;

    public CentralAuthAutoConfiguration(CentralAuthProperties properties) {
        this.properties = properties;
    }

    @PostConstruct
    public void init() {
        log.info("CentralAuthAutoConfiguration 初始化完成");
        log.info("CentralAuthAutoConfiguration 认证配置信息: {}", properties);
        if (StringUtils.isBlank(properties.getClientId())) {
            throw new IllegalArgumentException("central.auth.client-id must not be empty");
        }
        if (StringUtils.isBlank(properties.getClientSecret())) {
            throw new IllegalArgumentException("central.auth.client-secret must not be empty");
        }
        if (StringUtils.isBlank(properties.getTokenUrl())) {
            throw new IllegalArgumentException("central.auth.token-url must not be empty");
        }
    }

    // === 核心客户端配置 ===
    @Bean
    @ConditionalOnMissingBean
    @Lazy
    public CentralAuthClient centralAuthClient(
            CentralAuthProperties properties,
            ObjectProvider<CacheStrategy> cacheStrategyProvider
    ) {
        CacheStrategy strategy = cacheStrategyProvider.getIfAvailable(() -> {
            log.warn("没有找到缓存策略，使用默认内存缓存");
            return new MemoryCacheStrategy(properties.getTokenTtl());
        });

        log.info("创建 CentralAuthClient，使用缓存策略: {}",
                strategy.getClass().getSimpleName());
        return new CentralAuthClient(properties, strategy);
    }

    // === 非Redis缓存策略配置 ===
    @Bean(name = "cacheStrategy")
    @ConditionalOnProperty(
            name = "central.auth.cache-type",
            havingValue = "NONE"
    )
    @ConditionalOnMissingBean(name = "cacheStrategy")
    public CacheStrategy noCacheStrategy() {
        log.info("创建无缓存策略 (NoOpCacheStrategy)");
        return new NoOpCacheStrategy();
    }

    @Bean(name = "cacheStrategy")
    @ConditionalOnProperty(
            name = "central.auth.cache-type",
            havingValue = "MEMORY",
            matchIfMissing = true // 默认策略
    )
    @ConditionalOnMissingBean(name = "cacheStrategy")
    public CacheStrategy memoryCacheStrategy(CentralAuthProperties properties) {
        log.info("创建内存缓存策略 (MemoryCacheStrategy)");
        return new MemoryCacheStrategy(properties.getTokenTtl());
    }

    // === Redis相关配置 ===
    @Configuration
    @ConditionalOnProperty(
            name = "central.auth.cache-type",
            havingValue = "REDIS"
    )
    @ConditionalOnClass(name = "org.springframework.data.redis.connection.RedisConnectionFactory")
    static class RedisConfiguration {

        @Bean(name = "cacheStrategy")
        @ConditionalOnMissingBean(name = "cacheStrategy")
        public CacheStrategy redisCacheStrategy(
                RedisOperationsAdapter redisOperations,
                CentralAuthProperties properties
        ) {
            log.info("创建 Redis 缓存策略 (RedisCacheStrategy)");
            return new RedisCacheStrategy(redisOperations, properties.getTokenTtl());
        }

        @Bean
        @ConditionalOnMissingBean
        public RedisOperationsAdapter redisOperationsAdapter(
                RedisConnectionFactory redisFactory
        ) {
            log.info("创建 Redis 操作适配器 (DefaultRedisOperator)");
            return new DefaultRedisOperator(redisFactory);
        }
    }
}